package com.tian.service.impl;

import com.tian.config.RedisConfig;
import com.tian.dto.GoodsInfoDto;
import com.tian.dto.user.UserGoodsDto;
import com.tian.dto.user.UserGoodsReqDto;
import com.tian.dto.user.UserGoodsRespDto;
import com.tian.entity.*;
import com.tian.enums.ResultCode;
import com.tian.enums.StatusEnums;
import com.tian.mapper.GoodsInfoMapper;
import com.tian.mapper.UserActivityGoodsMapper;
import com.tian.mapper.UserMapper;
import com.tian.service.GoodsInfoService;
import com.tian.service.UserGoodsService;
import com.tian.util.CommonResult;
import com.tian.util.RedisConstantPre;
import com.tian.util.UserCacheUtil;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

import static com.tian.util.RedisConstantPre.GOODS_INFO_STOCK;
import static com.tian.util.RedisConstantPre.USER_POINT_LOCK_PRE;

/**
 * @author tianwc  公众号：java后端技术全栈、面试专栏
 * @version 1.0.0
 * @date 2023年06月09日 20:29
 * 博客地址：<a href="http://woaijava.cc/">博客地址</a>
 * <p>
 * 用户 积分兑换 商品
 */
@Service
public class UserGoodsServiceImpl implements UserGoodsService {
    @Resource
    private GoodsInfoMapper goodsInfoMapper;
    @Resource
    private RedisConfig redisConfig;
    @Resource
    private UserActivityGoodsMapper userActivityGoodsMapper;
    @Resource
    private GoodsInfoService goodsInfoService;
    @Resource
    private RedissonClient redissonClient;
    @Resource
    private UserMapper userMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public CommonResult<Boolean> exchange(UserGoodsDto userGoodsDto) {
        User user = UserCacheUtil.getUser();
        //先对商品上锁
        redissonClient.getLock(GOODS_INFO_STOCK + userGoodsDto.getGoodsId()).lock();
        try {

            CommonResult<GoodsInfoDto> goodsInfoResult = goodsInfoService.getById(userGoodsDto.getGoodsId());
            if (goodsInfoResult.getCode() != ResultCode.SUCCESS.getCode() || goodsInfoResult.getData() == null) {
                return CommonResult.failed(ResultCode.PARAMETER_ERROR);
            }
            GoodsInfoDto goodsInfoDto = goodsInfoResult.getData();
            //校验商品库存是否充足
            if (userGoodsDto.getCount() > goodsInfoDto.getStock()) {
                return CommonResult.failed(ResultCode.GOODS_STOCK_NO_ENOUGH);
            }
            //再对用户积分上锁
            redissonClient.getLock(USER_POINT_LOCK_PRE + userGoodsDto.getUserId()).lock();


            int totalPoint = userGoodsDto.getCount() * goodsInfoDto.getPoint();
            //校验积分是否充足
            if (totalPoint > user.getPoints()) {
                return CommonResult.failed(ResultCode.ACTIVITY_NO_ENOUGH);
            }
            //扣除商品库存

            GoodsInfo goodsInfo = new GoodsInfo();
            goodsInfo.setStock(goodsInfoDto.getStock() - userGoodsDto.getCount());
            goodsInfo.setId(goodsInfoDto.getId());
            goodsInfoMapper.updateByPrimaryKey(goodsInfo);
            //扣除用户积分
            user.setPoints(user.getPoints() - totalPoint);
            userMapper.updateUser(user);

            //用户兑换记录
            UserActivityGoods userActivityGoods=new UserActivityGoods();
            userActivityGoods.setUserId(user.getId());
            userActivityGoods.setGoodsInfoId(goodsInfo.getId());
            userActivityGoods.setStatus(StatusEnums.INIT.getStatus());
            userActivityGoodsMapper.insert(userActivityGoods);

            //删除缓存
            redisConfig.delete(RedisConstantPre.GOODS_INFO + goodsInfo.getId());
            redisConfig.delete(RedisConstantPre.USER_POINT_PRE + userGoodsDto.getUserId());
        } finally {

            //释放两把锁
            redissonClient.getLock(USER_POINT_LOCK_PRE + userGoodsDto.getUserId()).unlock();
            redissonClient.getLock(GOODS_INFO_STOCK + userGoodsDto.getGoodsId()).unlock();
        }
        return CommonResult.success();
    }

    @Override
    public CommonResult<UserGoodsRespDto> list(UserGoodsReqDto userGoodsReqDto) {
        return null;
    }
}
